<template>
  <div class="hasMany">
    <a-divider orientation="left" v-if="title">{{ title }}</a-divider>
    <a-space class="selectTable" v-if="selectTable" >
      <render v-model:value="selectValue" :data="selectTable"></render>
      <a-button size="small" @click="clear" v-if="value.length > 0 && (limit == 0 || limit > value.length) && !hideClear">
        <template #icon>
          <delete-outlined/>
        </template>
        {{ trans('FormMany.clear') }}
      </a-button>
    </a-space>
    <div v-if="table">
      <render :data="grid" :data-source="value" class="table" :custom-row="customRow" ref="dragRef">
        <template #bodyCell="{ column, record , text , index }">
          <a-space v-if="column.type =='action'">
            <template v-if="!disabled">
              <caret-up-filled @click="up(value,index)" v-if='hoverIndex == index && value.length > 1 && index > 0'>
                {{ trans('FormMany.up') }}
              </caret-up-filled>
              <caret-down-filled v-if='hoverIndex == index && value.length > 1 && index < value.length-1'
                                 @click="down(value,index)">{{ trans('FormMany.down') }}
              </caret-down-filled>
              <CopyOutlined v-if="!selectTable" @click="copy(record)"></CopyOutlined>
              <i class="far fa-arrow-alt-circle-left" v-if="!selectTable" style="cursor: pointer" @click="insert(index+1)"></i>
              <close-circle-filled style="color: red" v-if='hoverIndex == index && value.length > 0'
                                   @click="remove(index)">{{ trans('FormMany.remove') }}
              </close-circle-filled>
            </template>
          </a-space>
          <div v-else-if="column.type == 'sortManyDrag'">
            <a-tooltip placement="right" :title="trans('Grid.sortDrag')">
              <drag-outlined class="sortManyHandel" :data-field="column.dataIndex" style="font-weight:bold;cursor: grab"/>
            </a-tooltip>
          </div>
          <render :scopeProp="{$index:index,field:field,row:record,recursion:recursion}" :data="column.component"
                  @keyup.enter="()=>onEnter(index,column.enterAdd)" v-else></render>
        </template>
      </render>
      <div style="margin-top: 5px" v-if="!disabled && !selectTable">
        <a-button size="small" type='dashed' @click="add" v-if="(limit == 0 || limit > value.length) && !hideAdd">
          <template #icon>
            <plus-outlined/>
          </template>
          {{ trans('FormMany.add') }}
        </a-button>
        <a-button size="small" type='dashed'  @click="clear" v-if="value.length > 0 && (limit == 0 || limit > value.length) && !hideClear">
          <template #icon>
            <delete-outlined/>
          </template>
          {{ trans('FormMany.clear') }}
        </a-button>
      </div>
    </div>
    <template v-else>
      <div ref="dragRef">
        <template v-for="(item,index) in value" :key="item.ex_admin_id">
          <div :class="flex?'has-many-flex':''">
            <div style="flex: 1">
              <slot :$index="index" :field="field" :row="item" :recursion="recursion"></slot>
            </div>
            <a-form-item v-if="!disabled" class="action">
              <a-button class="sortManyHandel" size="small" type="dashed" v-if="drag">
                <template #icon>
                  <drag-outlined style="font-weight:bold;cursor: grab"/>
                </template>
              </a-button>
              <a-button size="small"
                        v-if="!flex && value.length - 1 == index && (limit == 0 || limit > value.length) && !hideAdd"
                        type="dashed" @click="add">
                <template #icon>
                  <plus-outlined/>
                </template>
                <span v-if="!flex">{{ trans('FormMany.add') }}</span>
              </a-button>

              <a-button type="dashed" size="small" @click="up(value,index)" v-show='value.length > 1 && index > 0'>
                <template #icon>
                  <caret-up-filled></caret-up-filled>
                </template>
                <span v-if="!flex">{{ trans('FormMany.up') }}</span>
              </a-button>
              <a-button type="dashed" size="small" v-show='value.length > 1 && index < value.length-1'
                        @click="down(value,index)">
                <template #icon>
                  <caret-down-filled></caret-down-filled>
                </template>
                <span v-if="!flex">{{ trans('FormMany.down') }}</span>
              </a-button>
              <a-button size="small" type="dashed" @click="copy(item)">
                <template #icon>
                  <CopyOutlined></CopyOutlined>
                </template>
                <span v-if="!flex">{{ trans('FormMany.copy') }}</span>
              </a-button>
              <a-button size="small" type="dashed" @click="insert(index+1)">
                <template #icon>
                  <arrow-left-outlined/>
                </template>
                <span v-if="!flex">{{ trans('FormMany.insert') }}</span>
              </a-button>
              <a-button size="small" type="dashed" v-show='value.length > 0' @click="remove(index)">
                <template #icon>
                  <close-circle-outlined/>
                </template>
                <span v-if="!flex">{{ trans('FormMany.remove') }}</span>
              </a-button>
              <a-button size="small" type="dashed"
                        v-if="!flex && value.length - 1 == index && (limit == 0 || limit > value.length) && !hideClear"
                        @click="clear">
                <template #icon>
                  <delete-outlined/>
                </template>
                <span v-if="!flex">{{ trans('FormMany.clear') }}</span>
              </a-button>
            </a-form-item>
          </div>
          <a-divider v-if="!flex"></a-divider>
        </template>
      </div>
      <a-form-item :labelCol='null' :colon="false" v-if="!disabled && flex">
        <a-button size="small" type='dashed' v-if="(limit == 0 || limit > value.length) && !hideAdd" @click="add">
          <template #icon>
            <plus-outlined/>
          </template>
          <span v-if="!flex">{{ trans('FormMany.add') }}</span>
        </a-button>
        <a-button size="small" type="dashed"
                  v-if="value.length > 0 && (limit == 0 || limit > value.length) && !hideClear" @click="clear">
          <template #icon>
            <delete-outlined/>
          </template>
          <span v-if="!flex">{{ trans('FormMany.clear') }}</span>
        </a-button>
      </a-form-item>
      <a-form-item :labelCol='null' :colon="false" v-else-if="!flex && value.length == 0 && !disabled && !hideAdd">
        <a-button size="small" type='dashed' @click="add">{{ trans('FormMany.add') }}</a-button>
      </a-form-item>
    </template>
  </div>
</template>
<script>
export default {
  name: 'ExFormMany'
}
</script>
<script setup>
import {useVModel} from '@vueuse/core'
import Sortable from 'sortablejs'
import {trans, ArrUp, ArrDown, setProxyData, arrFind, randomCoding} from "@/utils/index"
import {ref, onBeforeUnmount, nextTick, watch, toRaw,triggerRef} from 'vue'
import {orderBy, cloneDeep} from 'lodash'
import ajax from "@/utils/ajax";
import {action} from "@/store";
import {useInjectFormContext} from "@/components/form/context";

const props = defineProps({
  value: {
    type: Array,
    default: [],
  },
  limit: {
    type: Number,
    default: 0,
  },
  defaultRow: Number,
  disabled: Boolean,
  hideAdd: Boolean,
  hideClear: Boolean,
  drag: Boolean,
  itemData: Object,
  table: Boolean,
  field: String,
  sortField: String,
  title: String,
  columns: Array,
  grid: Object,
  recursion: {
    type: Array,
    default: [],
  },
  enterAdd: Boolean,
  flex: Boolean,
  content: Array,
  selectTable: [Object, Boolean],
  selectGridAjax: Object,
  gridRelationField: String,
})

const emit = defineEmits(['update:value'])
const hoverIndex = ref(-1)
const dragRef = ref()

const formContext = useInjectFormContext()
//默认添加行
if (props.defaultRow && props.value.length === 0) {
  for (let i = 0; i < props.defaultRow; i++) {
    props.value.push({...props.itemData})
  }
}
if(props.selectTable && props.grid){
  props.grid.attribute.columns.forEach(item=>{
    item.dataIndex = ['ex_admin_table',item.dataIndex]
  })
}
const value = useVModel(props, 'value', emit)
const selectValue = ref(value.value.map(item=>item[props.gridRelationField]))
if(props.selectTable){
  if(selectValue.value.length > 0){
    selectToTable()
  }
  watch(selectValue,val=>{
    selectToTable()
  })
}

watch(value, val => {
  addPkMark()
})
sort()
addPkMark()
function selectToTable() {
  const options = cloneDeep(props.selectGridAjax);
  Object.assign(options.data, {ex_eadmin_select_id: selectValue.value})
  if(formContext){
    options.data.data = formContext.submitData()
  }
  ajax(options).then(res => {
    value.value = res.data.attribute.dataSource.map(item=>{
      let find = arrFind(value.value,props.gridRelationField,item.ex_admin_id)
      if(find){
        find.ex_admin_table = item
      }else{
        find = {...props.itemData}
        find.ex_admin_table = item
        find[props.gridRelationField] = item.ex_admin_id
      }
      return find
    })
    setTimeout(()=>{
      sort()
    })
  })
}
function sort(){
  if (props.sortField) {
    value.value = orderBy(value.value, props.sortField)
  }
}
function addPkMark() {
  value.value.forEach((item, index) => {
    if(!item.ex_admin_id){
      item.ex_admin_id = randomCoding(20)
    }
    return item
  })
}

let sortable = null
if (props.drag) {
  nextTick(() => {
    let el, handle = '.sortManyHandel'
    if (props.table) {
      el = dragRef.value.$el.querySelectorAll(`.ant-table-content > table > tbody`)[0]
    } else {
      el = dragRef.value
    }
    sortable = Sortable.create(el, {
      animation: 1000,
      handle: handle,
      onEnd: evt => {
        var newIndex = evt.newIndex
        var oldIndex = evt.oldIndex
        if (props.table) {
          newIndex--
          oldIndex--
        }
        const targetRow = value.value.splice(oldIndex, 1)[0]
        value.value.splice(newIndex, 0, targetRow)
        sortMark()
      }
    })
  })
}
onBeforeUnmount((e) => {
  if (sortable) {
    sortable.destroy()
  }
})

//复制
function copy(data) {
  value.value.push(cloneDeep(data))
}

//回车添加
function onEnter(index, bool) {
  if (!props.disabled && props.enterAdd && bool && index === (value.value.length - 1)) {
    add()
  }
}

//添加元素
function add() {
  const data = cloneDeep(props.itemData)
  data.ex_admin_id = value.value.length + 1
  if (props.sortField) {
    data[props.sortField] = value.value.length
  }
  value.value.push(data)
}

//插入元素
function insert(index) {
  value.value.splice(index, 0, {...props.itemData})
}

//移除元素
function remove(index) {
  value.value.splice(index, 1)
  selectValue.value.forEach((id,index)=>{
    let find = arrFind(value.value,props.gridRelationField,id)
    if(!find){
      selectValue.value.splice(index, 1)
    }
  })

  sortMark()
}

//清空
function clear() {
  value.value.splice(0)
  selectValue.value.splice(0)
}

function customRow(record, index) {
  return {
    onMouseenter: (event) => {
      hoverIndex.value = index
    },
    onMouseleave: (event) => {
      hoverIndex.value = -1
    }
  };
}

function up(arr, index) {
  ArrUp(arr, index)
  sortMark()
}

function down(arr, index) {

  ArrDown(arr, index)
  sortMark()
}

function sortMark() {
  if (props.sortField) {
    value.value.forEach((item, index) => {
      item[props.sortField] = index
    })
  }
}

defineExpose({
  add,
  clear,
  copy
})
</script>

<style scoped>
.has-many-flex {
  display: flex;
  align-items: center;
}

.has-many-flex .action {
  margin-bottom: 0;
  margin-left: 8px;
}

.table .ant-form-item {
  margin-bottom: 0;
}

.has-many-flex :deep(.ant-collapse-header) {
  align-items: center !important;
}

.has-many-flex :deep(.ant-collapse) {
  margin-bottom: 3px;
}

.hasMany > .hasMany {
  margin-left: 30px;
}

.selectTable {
  margin-bottom: 10px;
}
</style>
